﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using KSSModel;
using OfficeOpenXml;

namespace KSSOnline.Controller
{
    public class KSSMaster
    {
        public static string createDocumentID()
        {
            string stringDoctype = "D";
            
            string dateString = DateTime.Today.ToString("ddMMyy");
            var year = DateTime.Today.Year;
            var month = DateTime.Today.Month;
            var autoID = getMaxRow().ToString();
            if (autoID.Length <= 7)
            {
                autoID = autoID.PadLeft(7, '0');
            }
            else
            {
                autoID = autoID.Substring(autoID.Length - 7, 7);
            }
            return stringDoctype + dateString + autoID;
        }
        public static string WriteCSV<T>(IEnumerable<T> items)
        {
            Type itemType = typeof(T);
            var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                .OrderBy(p => p.Name);
            var sb = new StringBuilder();
            sb.Append(string.Join(", ", props.Select(p => p.Name)));
            foreach (var item in items)
            {
                sb.Append(Environment.NewLine);
                sb.Append(string.Join(", ", props.Select(p => "'" + p.GetValue(item, null))));
            }
            string csv = sb.ToString();
            return csv;
        }

        public static byte[] ExportToExcel(List<object> datas)
        {

            using (ExcelPackage pck = new ExcelPackage())
            {
                //Create the worksheet
                ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Demo");
                ws.Cells["A1"].LoadFromCollection(datas, true);

                return pck.GetAsByteArray();
            }

            return null; ;
        }

        public static int getMaxRow()
        {
            using (var dataContext = new KSSDBDataContext())
            {
               
                try
                {
                    int row = (from doc in dataContext.tblDocs select doc.autoId).Max();
                    return row;
                }
                catch (Exception)
                {
                    Random rnd = new Random();
                    return rnd.Next(1, 100000);
                }
            }
        }
	public static bool AddLog(tblLog newLog)
        {
            using (var dataContext = new KSSDBDataContext())
            {
                newLog.datetime = DateTime.Now;
                try
                {
                    dataContext.tblLogs.InsertOnSubmit(newLog);
                    dataContext.SubmitChanges();
                }
                catch (Exception)
                {
                    return false;
                }

                return true;
            }
        }

        public static string ToHtmlControl(string controlType, string controlID, string controlName,string controlClass)
        {
            string HtmlTemplete = string.Empty; ;
            switch (controlType)
            {
                case "text":
                    HtmlTemplete = "<input type='text' name='{0}' id='{1}' class='{2}' />";
                    
                    break;
                case "cp":
                    HtmlTemplete = "<input type='checkbox' name='{0}' id='{1}' class='{2}' />";
                    break;
                case "rb":
                    HtmlTemplete = "<input type='radio' name='{0}' id='{1}' class='{2}' />";
                    break;
                case "area":
                    HtmlTemplete = "<textarea cols='80' rows='4' id='{1}' name='{2}' class='{3}'></textarea>";
                    break;
                default:
                    HtmlTemplete = "<input type='text' name='{0}' id='{1}' class='{2}' />";
                    break;
            }
            return string.Format(HtmlTemplete, controlID, controlName, controlClass);
        }
        public static string GetUniqueFileName(string name, string savePath, string ext)
        {

            name = name.Replace(ext, "").Replace(" ", "_");
            name = System.Text.RegularExpressions.Regex.Replace(name, @"[^\w\s]", "");

            var newName = name;
            var i = 0;
            if (System.IO.File.Exists(savePath + newName + ext))
            {

                do
                {
                    i++;
                    newName = name + "_" + i;

                }
                while (System.IO.File.Exists(savePath + newName + ext));

            }

            return newName;


        }
    
       
    }
    public class Result
    {
        public bool success;
        public string msg;
        public Result(bool Success, string Msg)
        {
            success = Success;
            msg = Msg;
        }
        public Result(bool Success)
        {
            success = Success;
        }
        public Result(string Msg)
        {
            msg = Msg;
        }
    }

    public enum SortOrder
    {
        ASC = 1,
        DESC = 2
    }
    public static class OrderByHelper
    {
        public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> enumerable, string orderBy)
        {
            return enumerable.AsQueryable().OrderBy(orderBy).AsEnumerable();
        }

        public static IQueryable<T> OrderBy<T>(this IQueryable<T> collection, string orderBy)
        {
            foreach (OrderByInfo orderByInfo in ParseOrderBy(orderBy))
                collection = ApplyOrderBy<T>(collection, orderByInfo);

            return collection;
        }

        private static IQueryable<T> ApplyOrderBy<T>(IQueryable<T> collection, OrderByInfo orderByInfo)
        {
            string[] props = orderByInfo.PropertyName.Split('.');
            Type type = typeof(T);

            ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg;
            foreach (string prop in props)
            {
                // use reflection (not ComponentModel) to mirror LINQ
                PropertyInfo pi = type.GetProperty(prop);
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
            string methodName = String.Empty;

            if (!orderByInfo.Initial && collection is IOrderedQueryable<T>)
            {
                if (orderByInfo.Direction == SortDirection.Ascending)
                    methodName = "ThenBy";
                else
                    methodName = "ThenByDescending";
            }
            else
            {
                if (orderByInfo.Direction == SortDirection.Ascending)
                    methodName = "OrderBy";
                else
                    methodName = "OrderByDescending";
            }

            //TODO: apply caching to the generic methodsinfos?
            return (IOrderedQueryable<T>)typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), type)
                .Invoke(null, new object[] { collection, lambda });

        }

        private static IEnumerable<OrderByInfo> ParseOrderBy(string orderBy)
        {
            if (String.IsNullOrEmpty(orderBy))
                yield break;

            string[] items = orderBy.Split(',');
            bool initial = true;
            foreach (string item in items)
            {
                string[] pair = item.Trim().Split(' ');

                if (pair.Length > 2)
                    throw new ArgumentException(String.Format("Invalid OrderBy string '{0}'. Order By Format: kkk, Property2 ASC, Property2 DESC", item));

                string prop = pair[0].Trim();

                if (String.IsNullOrEmpty(prop))
                    throw new ArgumentException("Invalid kkk. Order By Format: kkk, Property2 ASC, Property2 DESC");

                SortDirection dir = SortDirection.Ascending;

                if (pair.Length == 2)
                    dir = ("desc".Equals(pair[1].Trim(), StringComparison.OrdinalIgnoreCase) ? SortDirection.Descending : SortDirection.Ascending);

                yield return new OrderByInfo() { PropertyName = prop, Direction = dir, Initial = initial };

                initial = false;
            }

        }

        private class OrderByInfo
        {
            public string PropertyName { get; set; }
            public SortDirection Direction { get; set; }
            public bool Initial { get; set; }
        }

        private enum SortDirection
        {
            Ascending = 0,
            Descending = 1
        }
    }
}
